//
//  PNPacket.m
//  iRctl
//
//  Created by 城门虾米 on 2019/7/31.
//  Copyright © 2019 A. All rights reserved.
//

#import "PNPacket.h"


#pragma pack(1)
// 包
typedef struct {
    int8_t     packet_type;   // 包类型 0x01 控制 0x02 二进制流
    int32_t    length;     // data 长度
    char       data[];     // control 或 二进制流
} pn_packet_t;

// 控制消息
typedef struct {
    int32_t   packet_id;   // 0x00 unused
    int16_t   msg_id;      // 消息类型 控制协议用的，区分控制协议的类型 0x01 0x02
    char      data[];      // json
} pn_packet_control_t;

// 流数据
typedef struct {
    int8_t    stream_type;
    char      data[];
} pn_packet_stream_t;

#pragma pack()


@implementation PNPacket

- (instancetype) init {
    if (self = [super init]) {
        self.messageID = 0;
        self.packetID = 0;
    }
    return self;
}

+ (instancetype)packetWithBytes:(nullable const void *)buffer length:(NSUInteger)length {
    PNPacket* packet = [PNPacket new];
    packet.data = [NSData dataWithBytes:buffer length:length];
    
    pn_packet_t *pkt = (pn_packet_t *)buffer;
    packet.packetType = pkt->packet_type;
    if (pkt->packet_type == kPNPacketTypeControl) {
        pn_packet_control_t* ctl = (pn_packet_control_t*)pkt->data;
        packet.messageID = ctl->msg_id;
        packet.packetID = ctl->packet_id;
        NSData * data = [NSData dataWithBytes:ctl->data length:pkt->length - 6];
        NSError *err = nil;
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0x0 error:&err];
        if (!err) {
            packet.messageBody = dict;
        }
    } else if (pkt->packet_type == kPNPacketTypeStream) {
        pn_packet_stream_t* stream = (pn_packet_stream_t*)pkt->data;
        packet.streamType = stream->stream_type;
        packet.streamData = [NSData dataWithBytes:stream->data length:pkt->length - 1];
    }
    
    return packet;
}

+ (instancetype)packetWithPacketID:(int32_t)packetID msgID:(int16_t)msgID content:(NSDictionary*)content {
    
    NSError *err = nil;
    NSData *data = [NSJSONSerialization dataWithJSONObject:content options:0x0 error:&err];
    if (err != nil) {
        return nil;
    }
    
    char buf[10240] = {0};
    pn_packet_t *pkt = (pn_packet_t*)buf;
    pkt->packet_type = kPNPacketTypeControl;
    pkt->length = (int32_t)(sizeof(pn_packet_control_t) + data.length);
    
    pn_packet_control_t *msg = (pn_packet_control_t*)pkt->data;
    msg->msg_id = msgID;
    msg->packet_id = packetID;
    memcpy(msg->data, data.bytes, data.length);
    
    unsigned long pkt_len = sizeof(pn_packet_t) + pkt->length;
    
    PNPacket* packet = [PNPacket new];
    packet.data = [NSData dataWithBytes:pkt length:pkt_len];
    return packet;
}

+ (instancetype)packetWithStreamType:(int8_t)streamType streamData:(NSData *)data {
    
    size_t packetLength = sizeof(pn_packet_t) + sizeof(pn_packet_stream_t) + data.length;
    pn_packet_t* pkt = (pn_packet_t*)malloc(packetLength);

    pkt->packet_type = kPNPacketTypeStream;
    pkt->length = (int32_t)(sizeof(pn_packet_stream_t) + data.length);
    
    pn_packet_stream_t *stream = (pn_packet_stream_t *)pkt->data;
    stream->stream_type = streamType;
    memcpy(stream->data, data.bytes, data.length);
    
    PNPacket* packet = [PNPacket new];
    packet.data = [NSData dataWithBytes:pkt length:packetLength];
    free(pkt);
    return packet;
}

+ (int32_t)maybePacketWithBytes:(const void *)bytes length:(NSUInteger)length {
    if (bytes == nil) {
        return -1;
    }
    if (length < 5) {
        return -1;
    }
    pn_packet_t * pkt = (pn_packet_t*)bytes;
    
    int pkt_length = pkt->length + 5;
    if (length < pkt_length) {
        return -1;
    }
    return pkt_length;
}

@end
